#include <utils.hpp>

#define MAX_SIZE_PATH (1024 * 1024)

// 获取程序所在目录
char* GetPrgPath(void)
{
	char* prg_path = (char*)malloc(MAX_SIZE_PATH);
	memset(prg_path, 0, MAX_SIZE_PATH);
	readlink("/proc/self/exe", prg_path, MAX_SIZE_PATH);
	char* p = nullptr;
	if (nullptr != (p = strrchr(prg_path, '/')))
	{
		*p = '\0';
	}
	else
	{
		return nullptr;
	}
	return prg_path;
}

// 获取程序所在目录下的文件名
char* GetPrgFilePath(const char* filename)
{
	char* prg_path = GetPrgPath();
	if (prg_path == nullptr)
	{
		return nullptr;
	}

	char* file_path = (char*)malloc(MAX_SIZE_PATH);
	memset(file_path, 0, MAX_SIZE_PATH);

	snprintf(file_path, MAX_SIZE_PATH, "%s/%s", prg_path, filename);

	free(prg_path);
	return file_path;
}

// 创建目录
int MkDirPath(const char* path)
{
	char* dir_name = (char*)malloc(MAX_SIZE_PATH);
	strncpy(dir_name, path, MAX_SIZE_PATH);
	int len = strlen(dir_name);

	// 跳过根目录'/'
	for (int i = 1; i <= len; i++)
	{
		if (dir_name[i] == '/' || dir_name[i] == 0)
		{
			dir_name[i] = 0;
			if (access(dir_name, 3) != 0) // S_IRUSR | S_IWUSR
			{
				if (mkdir(dir_name, 0755) == -1)
				{
					return -1;
				}
			}
			dir_name[i] = '/';
		}
	}

	free(dir_name);

	return 0;
}

std::string StringTrimed(const std::string& str)
{
	size_t first = str.find_first_not_of(" \t\n\r\f\v"); // 查找第一个非空白字符
	if (std::string::npos == first)
	{
		return ""; // 如果没有找到非空白字符，返回原
	}

	size_t last = str.find_last_not_of(" \t\n\r\f\v"); // 查找最后一个非空白字符

	// 构造新的字符串，不包含首尾空白字符
	return str.substr(first, (last - first + 1));
}

// 将socket设置成非阻塞方式进行通信
int SocketNonBlocking(int socketFd)
{
	int flags  = 0;
	int status = 0;
	flags	   = fcntl(socketFd, F_GETFL, 0);
	if (flags == -1)
	{
		return -1;
	}
	flags |= O_NONBLOCK;
	status = fcntl(socketFd, F_SETFL, flags);
	if (status == -1)
	{
		return -1;
	}
	return 0;
}

// 设置socket缓冲区大小
int SocketSetBuffSize(int socket_fd, int recv_buff_size, int snd_buff_size)
{
	socklen_t optlen = sizeof(recv_buff_size);
	if (setsockopt(socket_fd, SOL_SOCKET, SO_RCVBUF, &recv_buff_size, optlen) < 0)
	{
		return -1;
	}

	optlen = sizeof(snd_buff_size);
	if (setsockopt(socket_fd, SOL_SOCKET, SO_SNDBUF, &snd_buff_size, optlen) < 0)
	{
		return -1;
	}
	return 0;
}

// 校验socket是否存活，活1, 死0
int SocketCheckAlive(int socketFd)
{
	struct tcp_info info;
	int len = sizeof(info);
	getsockopt(socketFd, IPPROTO_TCP, TCP_INFO, &info, (socklen_t*)&len);
	if ((info.tcpi_state == TCP_ESTABLISHED))
	{
		return 1;
	}
	return 0;
}